Setting Breakpoints and Inspecting Variables in Android Studio
Course: Android App Development
Topic: Setting Breakpoints and Inspecting Variables
Course Link: Android App Development Training
Demo Link: Register for a Free Course Demo
Website: JustAcademy
1. Introduction to Debugging in Android Development
Debugging is the process of identifying, analyzing, and fixing errors in an application. During Android app development, developers may encounter issues such as incorrect calculations, unexpected screen behavior, application crashes, incorrect API responses, and problems with data processing.
Android Studio provides a powerful debugging environment that allows developers to pause program execution, inspect variables, evaluate expressions, and execute code step by step. Two essential debugging techniques are setting breakpoints and inspecting variables.
A breakpoint pauses program execution at a selected line of code, while variable inspection allows developers to examine the current values of variables and objects during execution.
2. Learning Objectives
- Understand the purpose of debugging in Android applications.
- Learn how to create, enable, disable, and remove breakpoints.
- Inspect local variables, object properties, and method parameters.
- Use Step Over, Step Into, and Step Out during debugging.
- Evaluate expressions and monitor changing values.
- Identify logical errors and runtime issues efficiently.
- Apply debugging techniques to Kotlin-based Android applications.
3. What Is a Breakpoint?
A breakpoint is a debugging marker placed on a line of executable code. When the application reaches that line during a debugging session, execution pauses so that the developer can examine the program's current state.
Breakpoints help developers understand what the application is doing at a specific point instead of relying only on log messages or repeatedly modifying code.
Example
fun calculateTotal(price: Double, quantity: Int): Double {
val total = price * quantity
return total
}
Suppose the application calculates an incorrect total. A breakpoint placed on the line containing val total = price * quantity lets you inspect the values of price and quantity before the calculation is performed.
Benefits of Breakpoints
- Pause execution at important statements.
- Identify where unexpected values first appear.
- Examine method parameters and local variables.
- Follow the program's execution sequence.
- Reduce the need for excessive logging statements.
- Understand complex application logic more easily.
4. Types of Breakpoints in Android Studio
| Breakpoint Type |
Description |
Common Use |
| Line Breakpoint |
Pauses execution at a particular executable line. |
Inspecting calculations and function calls. |
| Conditional Breakpoint |
Pauses execution only when a specified Boolean condition is true. |
Investigating a problem that occurs for a particular input. |
| Exception Breakpoint |
Pauses execution when a selected exception is thrown, according to the breakpoint configuration. |
Investigating runtime exceptions. |
| Method Breakpoint |
Can pause when a method is entered or exited, depending on debugger support and configuration. |
Tracing method execution. |
| Field Watchpoint |
Monitors access to or modification of a supported field. |
Investigating unexpected object state changes. |
Line breakpoints are the most commonly used starting point. The availability and performance characteristics of other breakpoint types depend on the selected debugger, runtime, and code being debugged.
5. How to Set a Breakpoint in Android Studio
Follow these steps to create a line breakpoint in a Kotlin or Java source file.
- Open your Android project in Android Studio.
- Open the Kotlin or Java file containing the code you want to investigate.
- Locate an executable line where you want the application to pause.
- Click the gutter beside the line number. A breakpoint marker should appear.
- Run the application using the Debug command rather than a normal run.
- Perform the action that executes the selected code, such as tapping a button.
- When execution reaches the breakpoint, the debugger pauses the application or the relevant thread.
- Inspect the variables, call stack, and current execution line in the Debug tool window.
Important: A breakpoint does not normally pause the application when you simply open the screen. The program must execute the line containing the breakpoint.
Enable, Disable, and Remove Breakpoints
- Enable: Make an existing breakpoint active so that the debugger can stop there.
- Disable: Temporarily deactivate a breakpoint without deleting its configuration.
- Remove: Delete a breakpoint when it is no longer needed.
Click the breakpoint marker to toggle it, or use the breakpoint management interface in Android Studio to manage its settings. Exact controls may vary between IDE versions.
6. Running an Android Application in Debug Mode
Debug mode connects the application to the debugger, allowing the developer to pause execution and inspect program state.
Procedure
- Select the appropriate app run configuration.
- Choose the target Android emulator or connected device.
- Set one or more breakpoints in the source code.
- Click the Debug button in Android Studio.
- Wait for the application to launch.
- Perform the action required to reach the breakpoint.
- Inspect the paused program and resume execution when ready.
For example, if a breakpoint is placed inside a button click listener, tap that button in the running application to trigger the debugger.
7. Understanding the Debug Tool Window
When execution pauses, Android Studio provides several useful debugging panels. Their layout may differ depending on the IDE version.
| Panel or Feature |
Purpose |
| Variables |
Displays accessible local variables, parameters, and relevant object values. |
| Frames or Call Stack |
Shows the sequence of active method calls leading to the current execution point. |
| Watches |
Tracks selected expressions while stepping through the program. |
| Evaluate Expression |
Evaluates expressions in the current debugging context. |
| Debugger Controls |
Provides commands for stepping, resuming, and stopping execution. |
| Threads |
Helps inspect active application threads and their execution states. |
8. What Is Variable Inspection?
Variable inspection is the process of examining variable values while an application is paused in the debugger. It helps developers confirm whether the application is receiving the expected input, performing the correct calculations, and maintaining the right state.
Consider the following example:
fun calculateDiscount(price: Double, discount: Double): Double {
val discountAmount = price * discount / 100
val finalPrice = price - discountAmount
return finalPrice
}
If the debugger pauses inside this function, you can inspect the following values:
| Variable |
Example Value |
Meaning |
| price |
1000.0 |
Original price of the item. |
| discount |
10.0 |
Discount percentage. |
| discountAmount |
100.0 |
Calculated discount value. |
| finalPrice |
900.0 |
Price after applying the discount. |
These values help you determine whether the calculation is correct. If the discount is unexpectedly 0, you can investigate whether the wrong value was passed to the function.
9. Inspecting Local Variables
A local variable is declared within a function, method, or local scope. Its availability depends on the current execution location and the variable's lifetime.
Example
fun calculateArea(length: Int, width: Int): Int {
val area = length * width
return area
}
Set a breakpoint on the calculation line and call the function with known inputs. When execution pauses, inspect:
length — the first method parameter.
width — the second method parameter.
area — the computed value, once its initialization has executed.
If length = 5 and width = 4, the expected area is 20. Remember that a variable declared on the current line may not yet have its final value before that line executes.
10. Inspecting Function Parameters
Function parameters are values supplied when a function is called. Incorrect parameters are a common cause of unexpected application behavior.
fun greetUser(name: String, age: Int) {
val message = "Hello $name, age $age"
println(message)
}
Place a breakpoint inside greetUser() and trigger the function. Inspect name and age to verify that the calling code supplies the correct values.
This approach is particularly useful when data passes between activities, fragments, ViewModels, repositories, and API response handlers.
11. Inspecting Objects and Properties
Android applications frequently use objects to represent users, products, settings, API responses, and other data. The debugger can display an object's properties when they are accessible in the current context.
data class Product(
val name: String,
val price: Double,
val quantity: Int
)
fun calculateProductTotal(product: Product): Double {
return product.price * product.quantity
}
When execution pauses inside calculateProductTotal(), expand the product object in the Variables panel. Inspect its name, price, and quantity properties.
If the total is wrong, confirm that the object contains the expected values. For example, an incorrect quantity supplied by a form or API response can produce an incorrect total even when the multiplication is correct.
12. Using Step Over, Step Into, and Step Out
Stepping controls let you examine program execution one operation at a time.
| Command |
Purpose |
Example |
| Step Over |
Executes the current line and moves to the next relevant line without entering a called function. |
Run a calculation without opening every function it calls. |
| Step Into |
Enters a function call so that you can inspect its internal execution. |
Investigate why a helper function returns an incorrect result. |
| Step Out |
Continues execution until the current function returns to its caller. |
Finish inspecting a function and return to the calling method. |
| Resume Program |
Continues normal execution until another breakpoint or debugging event occurs. |
Move to the next breakpoint. |
Example of Step-by-Step Debugging
fun calculateTotal(price: Double, quantity: Int): Double {
val subtotal = price * quantity
val tax = subtotal * 0.18
val total = subtotal + tax
return total
}
Suppose price = 100.0 and quantity = 2. Place a breakpoint on the subtotal calculation and use Step Over to execute each line.
- Inspect
price and quantity.
- Execute the subtotal calculation. The expected subtotal is
200.0.
- Execute the tax calculation. The expected tax is
36.0.
- Execute the total calculation. The expected total is
236.0.
- Confirm the returned value.
This technique helps identify the exact statement where the actual value begins to differ from the expected value.
13. Creating Conditional Breakpoints
A conditional breakpoint pauses execution only when its configured condition evaluates to true. It is helpful when a function runs repeatedly and the problem occurs only for a specific input.
Example
fun processNumber(number: Int) {
val result = number * 2
println(result)
}
Suppose you want to investigate the function only when number == 10.
- Set a line breakpoint inside
processNumber().
- Open the breakpoint settings.
- Enter the condition
number == 10.
- Run the application in debug mode.
- Observe that the debugger pauses when the condition is satisfied.
Conditional breakpoints are especially useful in loops, repeated callbacks, list processing, and functions called by multiple screens. Make sure the condition uses a variable that is available at the breakpoint.
14. Evaluating Expressions During Debugging
The Evaluate Expression feature lets you evaluate an expression using the current debugging context. It can help you verify calculations and compare possible outcomes without permanently changing application source code.
Example
val price = 500.0
val quantity = 3
val total = price * quantity
While paused at an appropriate point, evaluate expressions such as:
price * quantity — calculates the expected total.
price / 2 — checks half the price.
quantity > 0 — checks whether the quantity is positive.
Expression evaluation depends on the current scope, available variable values, and debugger support. Expressions that call methods can have side effects, so prefer simple, read-only expressions when investigating application state.
15. Using Watches to Monitor Variables
A watch is an expression that you ask the debugger to track while you step through the code. Watches are useful for monitoring calculations or properties across multiple execution points.
var balance = 1000.0
balance -= 200.0
balance += 50.0
You could watch the expression balance and inspect its value as each statement executes.
| Execution Point |
Balance |
| Initial value |
1000.0 |
| After withdrawal |
800.0 |
| After deposit |
850.0 |
Watching a variable makes it easier to identify an unexpected state change. Add watches through the debugger's Watches panel or expression inspection controls available in your Android Studio version.
16. Debugging Android Button Click Events
Button click listeners are common locations for debugging because they often validate user input, update the interface, and initiate application operations.
Kotlin Example
binding.calculateButton.setOnClickListener {
val price = 100.0
val quantity = 3
val total = price * quantity
binding.resultText.text = "Total: $total"
}
To investigate this code:
- Set a breakpoint on the line that calculates
total.
- Run the application in debug mode.
- Tap the Calculate button.
- Inspect
price and quantity.
- Step over the calculation and inspect
total.
- Continue execution and check the displayed result.
If the debugger never pauses, verify that the correct button is being tapped, the listener is registered, and the code containing the breakpoint is actually executed.
17. Debugging ViewModels and Business Logic
In applications that use the MVVM architecture, ViewModels often contain screen-related business logic. Breakpoints help developers understand how user actions update state and produce results.
class PriceViewModel : ViewModel() {
fun calculateTotal(price: Double, quantity: Int): Double {
return price * quantity
}
}
Set a breakpoint inside calculateTotal() and trigger it from the UI or a unit test. Inspect the input parameters and returned value.
For more complex ViewModels, inspect state updates, validation results, coroutine execution, and values emitted through supported observable state mechanisms. When debugging asynchronous code, remember that the relevant work may run on a different thread or resume later.
18. Debugging Loops and Repeated Execution
Loops may execute many times, making them difficult to investigate with ordinary logging. A conditional breakpoint can help you stop at the iteration where the problem occurs.
for (index in 0 until 10) {
val square = index * index
println(square)
}
Place a breakpoint inside the loop and inspect index and square. If the issue occurs at index 5, a condition such as index == 5 can help you focus on that iteration.
When debugging loops, verify the initial value, loop condition, increment behavior, array or collection boundaries, and the value calculated during each iteration.
19. Debugging Null Values and Unexpected State
Null-related problems can occur when data is absent, an API response is incomplete, a property has not been initialized, or a value is unexpectedly cleared.
fun displayUserName(name: String?) {
val displayName = name ?: "Guest"
println(displayName)
}
Set a breakpoint before the fallback expression and inspect name. If it is null, investigate where the value originated and whether the calling code supplied the expected data.
Kotlin's null-safety features reduce certain classes of errors, but nullable API responses, Java interoperability, and incorrect application state can still require debugging.
20. Best Practices for Breakpoints and Variable Inspection
- Place breakpoints on executable statements rather than blank lines or comments.
- Start with a small number of breakpoints near the suspected problem.
- Inspect inputs before inspecting calculated outputs.
- Use conditional breakpoints for repeated operations.
- Use Step Into only when you need to investigate a called function.
- Use watches for values that must be monitored throughout execution.
- Check the call stack to understand how the current method was reached.
- Remove or disable temporary breakpoints when they are no longer needed.
- Avoid evaluating expressions that change application state unless that behavior is intentional.
- Do not assume that a value shown in the debugger represents the state after the current line has executed.
- Test the fix after debugging to ensure the problem has actually been resolved.
- Avoid logging passwords, authentication tokens, personal data, or other sensitive information.
21. Common Debugging Problems and Solutions
| Problem |
Possible Cause |
Solution |
| Breakpoint does not trigger |
The selected line is not executed. |
Confirm the execution path and reproduce the action that reaches the line. |
| Breakpoint appears inactive |
The breakpoint is disabled or the debugger cannot bind it correctly. |
Enable it and verify the source file and active debug session. |
| Variable is not visible |
The variable is outside the current scope or has not been initialized. |
Move to an appropriate execution point and inspect the correct stack frame. |
| Value differs from expectation |
Incorrect input, calculation, or state update. |
Inspect parameters and step through the relevant statements. |
| Application appears frozen |
Execution is paused at a breakpoint. |
Resume execution or stop the debugging session when appropriate. |
| Conditional breakpoint never triggers |
The condition is false, invalid, or references an unavailable variable. |
Verify the condition and inspect the actual values at the selected line. |
| Incorrect source mapping |
Stale build output or code transformation complicates debugging. |
Confirm the active build variant and source, then rebuild if necessary. |
| Asynchronous code is difficult to follow |
Execution continues on another thread or resumes later. |
Inspect thread information and set breakpoints at the relevant callbacks or coroutine code. |
22. Practical Exercise: Debug a Shopping Total Calculator
Objective: Use breakpoints and variable inspection to identify incorrect values in a simple shopping calculation.
Sample Code
fun calculateShoppingTotal(
price: Double,
quantity: Int,
discountPercent: Double
): Double {
val subtotal = price * quantity
val discountAmount = subtotal * discountPercent / 100
val finalTotal = subtotal - discountAmount
return finalTotal
}
fun main() {
val total = calculateShoppingTotal(
price = 200.0,
quantity = 3,
discountPercent = 10.0
)
println("Final Total: $total")
}
Tasks
- Set a breakpoint on the subtotal calculation.
- Run the program in debug mode.
- Inspect the values of
price, quantity, and discountPercent.
- Use Step Over to calculate the subtotal.
- Inspect the discount amount.
- Inspect the final total before returning from the function.
- Repeat the exercise with a quantity of zero and a discount of 25%.
- Set a conditional breakpoint to investigate only calls where
quantity == 3.
Expected Results
| Variable |
Expected Value |
| price |
200.0 |
| quantity |
3 |
| discountPercent |
10.0 |
| subtotal |
600.0 |
| discountAmount |
60.0 |
| finalTotal |
540.0 |
Learning outcome: You should be able to follow execution from input parameters through intermediate calculations and verify the returned result.
23. Interview Questions and Answers
Q1. What is a breakpoint in Android Studio?
A breakpoint is a marker on an executable line that allows the debugger to pause program execution so the developer can inspect the application state.
Q2. What is the difference between Run and Debug?
Run launches the application normally, whereas Debug connects the debugger so developers can pause execution, inspect variables, and step through code.
Q3. How do you set a breakpoint?
Open the source file and click the gutter beside the desired executable line. Then launch the application in debug mode and execute that line.
Q4. What is variable inspection?
Variable inspection is the process of examining current values of local variables, parameters, and accessible object properties during debugging.
Q5. What is a conditional breakpoint?
A conditional breakpoint pauses execution only when its specified condition is satisfied, helping developers investigate particular inputs or iterations.
Q6. What is the difference between Step Over and Step Into?
Step Over executes the current line without entering a called function, while Step Into enters the function so its internal statements can be examined.
Q7. What is the purpose of the call stack?
The call stack shows active method calls and helps identify the sequence of operations that led to the current execution point.
Q8. What are watches used for?
Watches allow developers to monitor selected expressions while stepping through code, making it easier to identify unexpected changes in values.
Q9. Why might a breakpoint not trigger?
The line may not be executed, the breakpoint may be disabled, the condition may be false, or the breakpoint may not be correctly associated with the active source code.
Q10. Can debugging help identify logical errors?
Yes. By inspecting inputs, intermediate results, control flow, and return values, developers can identify logical errors even when the application does not crash.
24. Quick Revision Checklist
- Understand the purpose of breakpoints.
- Know how to set, enable, disable, and remove breakpoints.
- Run the application using Debug mode.
- Inspect function parameters and local variables.
- Expand objects to examine their properties.
- Use Step Over, Step Into, and Step Out appropriately.
- Configure conditional breakpoints for specific scenarios.
- Use watches and expression evaluation when helpful.
- Investigate unexpected values by tracing their origin.
- Verify that the corrected application behaves as expected.
25. Conclusion
Setting breakpoints and inspecting variables are fundamental skills for Android developers. They provide direct insight into program execution, making it easier to understand application behavior, identify incorrect values, investigate logical errors, and resolve runtime issues.
By practicing these techniques in Android Studio, developers can debug Kotlin and Java code more systematically and build more reliable Android applications. Regular practice with line breakpoints, conditional breakpoints, watches, expression evaluation, and stepping controls will improve debugging confidence and development efficiency.
Learn Android App Development with JustAcademy
Strengthen your Android development skills through structured learning and practical exercises.
Explore the Android App Development Course
Register for a Course Demo
Visit the JustAcademy Website